/**
 * Copyright 2008 Adam Ruggles.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package kiff.service.impl;

import java.util.Date;

import kiff.dao.CoreDAO;
import kiff.dao.GlobalAclDAO;
import kiff.dao.UserDAO;
import kiff.entity.GlobalAcl;
import kiff.entity.GlobalPermission;
import kiff.entity.User;
import kiff.exception.DataLayerException;
import kiff.exception.ServiceLayerException;
import kiff.security.Acl;
import kiff.service.UserService;
import kiff.util.PasswordUtils;

import com.google.inject.Inject;

/**
 * An implementation of the UserService interface.
 * @author Adam
 * @version $Id: UserServiceImpl.java 69 2008-11-26 19:25:42Z a.ruggles $
 */
public class UserServiceImpl extends AbstractService<User> implements UserService {
	/**
	 * Global Access Control List Data Access Object.
	 */
	private GlobalAclDAO globalAclDAO;

	/**
	 * {@inheritDoc}
	 * Note: This method can be removed after upgrading to Guice 2.0.
	 * @see kiff.service.impl.AbstractService#setDao(kiff.dao.CoreDAO)
	 */
	@Inject(optional = true)
	public void setDao(final CoreDAO<User> dao) {
		this.dao = dao;
	}

	/**
	 * {@inheritDoc}
	 * @see kiff.service.impl.AbstractService#insert(kiff.entity.CoreEntity, kiff.entity.User)
	 */
	@Override
	public void insert(final User entity, final User user) throws ServiceLayerException {
		try {
			Date timestamp = new Date();
			entity.setCreator(user);
			entity.setCreated(timestamp);
			entity.setModified(timestamp);
			String password = entity.getPassword();
			entity.setSeed(PasswordUtils.randomLong());
			entity.setPassword(PasswordUtils.generate(password, entity.getSeed()));
			if (entity.getActive() == null) {
				entity.setActive(false);
			}
            dao.insert(entity);
        } catch (DataLayerException dataLayerException) {
            throw new ServiceLayerException(dataLayerException);
        }
	}

	/**
	 * {@inheritDoc}
	 * @see kiff.service.UserService#validate(java.lang.String, java.lang.String)
	 */
	public User validate(final String username, final String password) throws ServiceLayerException {
		if (username == null || password == null) {
			return null;
		}
		try {
			User user = ((UserDAO) dao).getByUsername(username);
			if (user != null) {
				// Validate password.
				String generated = PasswordUtils.generate(password, user.getSeed());
				if (generated.equals(user.getPassword())) {
					Acl acl = globalAclDAO.findByName(GlobalAcl.DEFAULT_NAME);
					user.setAdministrator(acl.hasPermission(user.getRoles(),
							new GlobalPermission(GlobalPermission.ADMINISTRATOR)));
					user.setModerator(acl.hasPermission(user.getRoles(),
							new GlobalPermission(GlobalPermission.MODERATOR)));
					return user;
				}
			}
			return null;
		} catch (DataLayerException dataLayerException) {
            throw new ServiceLayerException(dataLayerException);
        }
	}

	/**
	 * Sets globalAclDAO.
	 * @param globalAclDAO the globalAclDAO to set.
	 */
	@Inject
	public void setGlobalAclDAO(final GlobalAclDAO globalAclDAO) {
		this.globalAclDAO = globalAclDAO;
	}
}
